﻿#ifndef FLOWDATA_H
#define FLOWDATA_H

#include <QObject>
#include <QVector>
#include <QTimer>
#include <climits>
#include <QTableWidget>
#include <QDateTime>
#include <QtMath>
#include "OpcUA/opcua_qthread.h"
#include "OpcUA/plcdataconversion.h"

//单条流程参数结构体
struct FlowParam {
    int16_t step = -1;                  // Step列（0列）
    int16_t durationTime = -1;          // Duration Time(s)列（1列）
    int16_t totalTime = -1;             // Total Time(s)列（2列）
    int16_t setTemp1 = -1;              // Set Temprature 1列（3列）
    int16_t setTemp2 = -1;              // Set Temprature 2列（4列）
    int16_t setPressure = -1;           // Set Pressure列（5列）

    // Mo1组（6-10列）
    int16_t mo1Source = -1;
    int16_t mo1Push = -1;
    bool    mo1Line = false;
    bool    mo1LineIsEmpty = true; //用于判断输入是否空值
    bool    mo1Run = false;
    bool    mo1RunIsEmpty = true; //用于判断输入是否空值
    int16_t mo1Press = -1;

    // Mo2组（11-15列）
    int16_t mo2Source = -1;
    int16_t mo2Push = -1;
    bool    mo2Line = false;
    bool    mo2LineIsEmpty = true; //用于判断输入是否空值
    bool    mo2Run = false;
    bool    mo2RunIsEmpty = true; //用于判断输入是否空值
    int16_t mo2Press = -1;

    // O-1组（16-19列）
    int16_t o1Source = -1;
    int16_t o1Push = -1;
    bool    o1Line = false;
    bool    o1LineIsEmpty = true; //用于判断输入是否空值
    bool    o1Run = false;
    bool    o1RunIsEmpty = true; //用于判断输入是否空值

    // O-2组（20-23列）
    int16_t o2Source = -1;
    int16_t o2Push = -1;
    bool    o2Line = false;
    bool    o2LineIsEmpty = true; //用于判断输入是否空值
    bool    o2Run = false;
    bool    o2RunIsEmpty = true; //用于判断输入是否空值

    // N2组（24-25列）
    int16_t N2Source = -1;
    bool    N2Valve = false ;
    bool    N2ValveIsEmpty = true; //用于判断输入是否空值
};

class FlowData : public QObject
{
    Q_OBJECT
public:
    explicit FlowData(OpcUA_QThread *opcUA, QObject *parent = nullptr);

    void setTemperature(int16_t temperature1, int16_t temperature2);

    /**
     * @brief isValidUInt16 0-32767整数校验
     * @param text 输入字符串
     * @param outValue 转换后的输出结果
     * @return 成功返回true，失败返回false
     */
    bool isValidUInt16(const QString& text, int16_t& outValue);

    /**
     * @brief isValidLineRunValue Line/Run列整数校验
     * @param text 输入字符串
     * @param outValue 转换后的输出结果
     * @return 成功返回true，失败返回false
     */
    bool isValidLineRunValue(const QString& text, int& outValue);

    /**
     * @brief validateTableData 验证表格数据合法性
     * @param col 列索引
     * @param text 输入文本
     * @return 合法返回true，否则返回false
     */
    bool validateTableData(int col, const QString& text);

    /**
     * @brief updateTotalTime 更新Total Time列数据
     * @param table 表格对象
     * @param headerRowCount 表头行数
     */
    void updateTotalTime(QTableWidget* table, int headerRowCount);

    /**
     * @brief updateParamFromTable 从表格更新参数列表
     * @param table 表格对象
     * @param row 行索引
     * @param headerRowCount 表头行数
     */
    void updateParamFromTable(QTableWidget* table, int row, int headerRowCount);

    /**
     * @brief saveParamsFromTable 从表格保存参数列表
     * @param table 表格对象
     * @param headerRowCount 表头行数
     * @return 保存的有效参数数量
     */
    int saveParamsFromTable(QTableWidget* table, int headerRowCount);

    /**
     * @brief shouldSwitchStep 判断是否需要切换步骤
     * @param params 参数列表
     * @param currentIndex 当前步骤索引
     * @param elapsedSec 已运行时间（秒）
     * @return 需要切换返回true，否则返回false
     */
    bool shouldSwitchStep(const QVector<FlowParam>& params, int currentIndex, double elapsedSec);

    /**
     * @brief addParam 添加单条参数到列表
     * @param param 流程参数
     */
    void addParam(const FlowParam& param);

    void clearParams();

    /**
     * @brief getParams 获取参数列表
     * @return 参数列表
     */
    QVector<FlowParam> getParams() const;

    /**
     * @brief calculateTotalTime 计算Total Time
     * @param durationList 持续时间列表
     * @param index 当前索引
     * @return 计算后的Total Time
     */
    int16_t calculateTotalTime(const QVector<int16_t>& durationList, int index);

    /**
     * @brief writeStepToKepserver 写入单步参数到Kepserver
     * @param param 流程参数
     */
    void writeStepToKepserver(const FlowParam& param);

    /**
     * @brief stopWrite 停止写入操作
     */
    void stopWrite();

    /**
     * @brief setActiveStatus   设置FlowChart是否在工作状态，ture才会持续写入温度
     * @param status
     */
    void setActiveStatus(bool status);

signals:
    void paramRangeError(const QString& errMsg);  //参数错误信号
    void writeSuccess(const QString& msg);         //写入成功信号

private slots:
    //定时写入温度
    void on_timeOut_temperatureWrite();

    void on_writeDataFromHomePage(bool success);

private:
    /**
     * @brief 解析表格中的16位整数参数并赋值
     * @param table 指向QTableWidget的指针，包含需要解析的数据
     * @param row 要解析的行索引
     * @param col 要解析的列索引
     * @param param 引用参数，用于存储解析后的16位整数值
     * @note 若表格项不存在则不进行赋值操作，保持参数原有值
     */
    void parseInt16Param(QTableWidget* table, int row, int col, int16_t& param);

    /**
     * @brief 解析表格中的Line/Run参数并转换为布尔值
     * @param table 指向QTableWidget的指针，包含需要解析的数据
     * @param row 要解析的行索引
     * @param col 要解析的列索引
     * @param param 引用参数，用于存储转换后的布尔值（非0值转为true）
     * @note 若表格项不存在则不进行赋值操作，保持参数原有值
     */
    void parseBoolParam(QTableWidget* table, int row, int col, bool& param, bool& isEmpty);

    /**
     * @brief parseRowToParam 将表格行数据转换为FlowParam结构体
     * @param table 表格对象
     * @param row 行索引
     * @return 转换后的FlowParam对象
     */
    FlowParam parseRowToParam(QTableWidget* table, int row);

    /**
     * @brief getAllDurationTime 获取所有行的Duration Time
     * @param table 表格对象
     * @param headerRowCount 表头行数
     * @return Duration Time列表
     */
    QVector<int16_t> getAllDurationTime(QTableWidget* table, int headerRowCount);

    /**
     * @brief convertParam  转换数据值
     * @param original  传入数据
     * @return          返回转换后的数据
     */
    FlowParam convertParam(const FlowParam& original);


    int16_t calculateTemperatureIncrement(int16_t targetTemp, int16_t currentTemp, int16_t duration);

private:
    OpcUA_QThread *m_opcUA;                //OPCUA通信对象
    QVector<FlowParam> m_flowParams;       //流程参数列表
    const int16_t m_maxValue = INT16_MAX;  //参数最大值（32767）
    const int16_t m_minValue = 0;          //参数最小值（0）
    bool m_isWriting = false;              //写入状态标记

    bool m_flowChartIsActive = false;       //活跃标志
    QTimer * my_temperatureWriteTimer;      //温度写入定时器
    FlowParam m_prevParam;  // 保存上一次有效参数

    qint64 m_stepStartTime = 0;  //步骤开始的时间（毫秒）

    int16_t m_temperature1;   //当前温度1
    int16_t m_temperature2;   //当前温度2
};

#endif // FLOWDATA_H
